package com.codeplatform.service.impl;

import com.codeplatform.dto.*;
import com.codeplatform.entity.User;
import com.codeplatform.entity.UserSession;
import com.codeplatform.mapper.UserMapper;
import com.codeplatform.mapper.UserSessionMapper;
import com.codeplatform.service.AuthService;
import com.codeplatform.util.JwtUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;

/**
 * 用户认证服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AuthServiceImpl implements AuthService {
    
    private final UserMapper userMapper;
    private final UserSessionMapper userSessionMapper;
    private final JwtUtil jwtUtil;
    private final PasswordEncoder passwordEncoder;
    

    
    /**
     * 用户注册
     */
    @Override
    @Transactional
    public AuthResponse register(RegisterRequest request) {
        try {
            // 验证密码是否一致
            if (!request.isPasswordMatch()) {
                throw new RuntimeException("两次输入的密码不一致");
            }
            
            // 检查用户名是否已存在
            if (!isUsernameAvailable(request.getUsername())) {
                throw new RuntimeException("用户名已存在");
            }
            
            // 检查邮箱是否已存在
            if (!isEmailAvailable(request.getEmail())) {
                throw new RuntimeException("邮箱已被注册");
            }
            

            
            // 创建用户
            User user = new User();
            user.setUsername(request.getUsername());
            user.setPassword(passwordEncoder.encode(request.getPassword()));
            user.setEmail(request.getEmail());
            user.setNickname(request.getNickname() != null ? request.getNickname() : request.getUsername());
            user.setRole("user");
            user.setStatus(1);
            user.setEmailVerified(false); // 邮箱未验证

            user.setCreatedAt(LocalDateTime.now());
            user.setUpdatedAt(LocalDateTime.now());
            
            userMapper.insert(user);
            
            // 生成令牌
            Map<String, String> tokens = jwtUtil.generateTokenPair(
                user.getId(), user.getUsername(), user.getRole());
            
            // 创建用户会话
            createUserSession(user.getId(), tokens.get("accessToken"), tokens.get("refreshToken"));
            
            // 构建用户信息
            AuthResponse.UserInfo userInfo = AuthResponse.UserInfo.builder()
                    .id(user.getId())
                    .username(user.getUsername())
                    .nickname(user.getNickname())
                    .email(user.getEmail())
                    .avatar(user.getAvatar())
                    .role(user.getRole())
                    .status(convertStatusToString(user.getStatus()))
                    .emailVerified(user.getEmailVerified())

                    .createdAt(user.getCreatedAt())
                    .lastLoginAt(user.getLastLoginAt())
                    .build();
            

            
            log.info("用户注册成功: {}", user.getUsername());
            
            return AuthResponse.success(
                tokens.get("accessToken"),
                tokens.get("refreshToken"),
                jwtUtil.getTokenRemainingTime(tokens.get("accessToken")),
                jwtUtil.getTokenRemainingTime(tokens.get("refreshToken")),
                userInfo
            );
        } catch (Exception e) {
            log.error("用户注册失败", e);
            throw new RuntimeException("注册失败: " + e.getMessage());
        }
    }
    
    /**
     * 用户登录
     */
    @Override
    @Transactional
    public AuthResponse login(LoginRequest request) {
        try {
            // 查找用户
            User user = findUserByUsernameOrEmail(request.getUsernameOrEmail());
            if (user == null) {
                throw new RuntimeException("用户名或密码错误");
            }
            
            // 验证密码
            if (!passwordEncoder.matches(request.getPassword(), user.getPassword())) {
                throw new RuntimeException("用户名或密码错误");
            }
            
            // 检查用户状态（1-正常，0-禁用，2-待验证）
            if (user.getStatus() == null || user.getStatus() != 1) {
                String statusMessage = "账户状态异常";
                if (user.getStatus() != null) {
                    switch (user.getStatus()) {
                        case 0:
                            statusMessage = "账户已被禁用";
                            break;
                        case 2:
                            statusMessage = "账户待验证，请先验证邮箱";
                            break;
                        default:
                            statusMessage = "账户状态异常";
                    }
                }
                throw new RuntimeException(statusMessage);
            }
            
            // 生成令牌
            Map<String, String> tokens = jwtUtil.generateTokenPair(
                user.getId(), user.getUsername(), user.getRole());
            
            // 创建用户会话
            createUserSession(user.getId(), tokens.get("accessToken"), tokens.get("refreshToken"));
            
            // 更新最后登录时间
            user.setLastLoginAt(LocalDateTime.now());
            userMapper.updateById(user);
            
            // 构建用户信息
            AuthResponse.UserInfo userInfo = AuthResponse.UserInfo.builder()
                    .id(user.getId())
                    .username(user.getUsername())
                    .nickname(user.getNickname())
                    .email(user.getEmail())
                    .avatar(user.getAvatar())
                    .role(user.getRole())
                    .status(convertStatusToString(user.getStatus()))
                    .emailVerified(user.getEmailVerified())

                    .createdAt(user.getCreatedAt())
                    .lastLoginAt(user.getLastLoginAt())
                    .build();
            
            log.info("用户登录成功: {}", user.getUsername());
            
            return AuthResponse.success(
                tokens.get("accessToken"),
                tokens.get("refreshToken"),
                jwtUtil.getTokenRemainingTime(tokens.get("accessToken")),
                jwtUtil.getTokenRemainingTime(tokens.get("refreshToken")),
                userInfo
            );
            
        } catch (Exception e) {
            log.error("用户登录失败", e);
            throw new RuntimeException("登录失败: " + e.getMessage());
        }
    }
    
    /**
     * 刷新令牌
     */
    @Override
    @Transactional
    public AuthResponse refreshToken(RefreshTokenRequest request) {
        try {
            String refreshToken = request.getRefreshToken();
            
            // 验证刷新令牌
            if (!jwtUtil.validateRefreshToken(refreshToken)) {
                throw new RuntimeException("刷新令牌无效或已过期");
            }
            
            // 从数据库验证会话
            UserSession session = userSessionMapper.findByRefreshToken(refreshToken);
            if (session == null || !session.isValid()) {
                throw new RuntimeException("会话无效或已过期");
            }
            Long userId = jwtUtil.getUserIdFromToken(refreshToken);
            String username = jwtUtil.getUsernameFromToken(refreshToken);
            
            // 获取用户信息
            User user = userMapper.selectById(userId);
            if (user == null) {
                throw new RuntimeException("用户不存在");
            }
            
            // 生成新的访问令牌
            String newAccessToken = jwtUtil.generateAccessToken(userId, username, user.getRole());
            
            // 更新会话
            session.setSessionToken(newAccessToken);
            session.setUpdatedAt(LocalDateTime.now());
            session.updateLastActive();
            userSessionMapper.updateById(session);
            
            log.info("令牌刷新成功: {}", username);
            
            return AuthResponse.refreshSuccess(
                newAccessToken,
                jwtUtil.getTokenRemainingTime(newAccessToken)
            );
            
        } catch (Exception e) {
            log.error("令牌刷新失败", e);
            throw new RuntimeException("令牌刷新失败: " + e.getMessage());
        }
    }
    
    /**
     * 用户登出
     */
    @Override
    @Transactional
    public Boolean logout(String token) {
        try {
            Long userId = jwtUtil.getUserIdFromToken(token);
            if (userId == null) {
                return false;
            }
            
            // 删除用户会话
            userSessionMapper.deleteBySessionToken(token);
            
            log.info("用户登出成功: userId={}", userId);
            return true;
            
        } catch (Exception e) {
            log.error("用户登出失败", e);
            return false;
        }
    }
    
    /**
     * 验证令牌
     */
    @Override
    public User validateToken(String token) {
        try {
            if (!jwtUtil.validateAccessToken(token)) {
                return null;
            }
            
            Long userId = jwtUtil.getUserIdFromToken(token);
            if (userId == null) {
                return null;
            }
            
            // 验证会话是否存在且有效
            UserSession session = userSessionMapper.findBySessionToken(token);
            if (session == null || !session.isValid()) {
                return null;
            }

            // 更新最后活跃时间
            session.updateLastActive();
            userSessionMapper.updateById(session);

            return userMapper.selectById(userId);
            
        } catch (Exception e) {
            log.error("令牌验证失败", e);
            return null;
        }
    }
    
    /**
     * 检查用户名是否可用
     */
    @Override
    public Boolean isUsernameAvailable(String username) {
        return userMapper.existsByUsername(username) == 0;
    }
    
    /**
     * 检查邮箱是否可用
     */
    @Override
    public Boolean isEmailAvailable(String email) {
        return userMapper.existsByEmail(email) == 0;
    }
    
    /**
     * 修改密码
     */
    @Override
    @Transactional
    public Boolean changePassword(Long userId, String oldPassword, String newPassword) {
        try {
            User user = userMapper.selectById(userId);
            if (user == null) {
                return false;
            }
            
            // 验证旧密码
            if (!passwordEncoder.matches(oldPassword, user.getPassword())) {
                throw new RuntimeException("原密码错误");
            }
            
            // 更新密码
            user.setPassword(passwordEncoder.encode(newPassword));
            user.setUpdatedAt(LocalDateTime.now());
            userMapper.updateById(user);

            // 删除所有会话，强制重新登录
            userSessionMapper.deleteByUserId(userId);
            
            log.info("密码修改成功: userId={}", userId);
            return true;
            
        } catch (Exception e) {
            log.error("密码修改失败", e);
            return false;
        }
    }
    
    /**
     * 重置密码（通过邮箱）
     */
    @Override
    public Boolean resetPassword(String email) {
        try {
            User user = userMapper.findByEmail(email);
            if (user == null) {
                // 为了安全，不暴露邮箱是否存在
                return true;
            }
            
            // 生成重置令牌并发送邮件
            String resetToken = UUID.randomUUID().toString();
            
            // 这里应该发送重置密码邮件
            // emailService.sendPasswordResetEmail(email, resetToken);
            
            log.info("密码重置邮件已发送: {}", email);
            return true;
            
        } catch (Exception e) {
            log.error("密码重置失败", e);
            return false;
        }
    }
    
    /**
     * 激活用户账户
     */
    @Override
    @Transactional
    public Boolean activateAccount(String token) {
        try {
            // 这里应该验证激活令牌
            // 简化实现，实际项目中需要更复杂的逻辑
            
            log.info("账户激活成功");
            return true;
            
        } catch (Exception e) {
            log.error("账户激活失败", e);
            return false;
        }
    }
    

    
    /**
     * 根据用户名或邮箱查找用户
     */
    private User findUserByUsernameOrEmail(String usernameOrEmail) {
        if (usernameOrEmail.contains("@")) {
            return userMapper.findByEmail(usernameOrEmail);
        } else {
            return userMapper.findByUsername(usernameOrEmail);
        }
    }
    
    /**
     * 创建用户会话
     */
    /**
     * 将用户状态整数转换为字符串
     * @param status 状态整数（0-禁用，1-正常，2-待验证）
     * @return 状态字符串
     */
    private String convertStatusToString(Integer status) {
        if (status == null) {
            return "unknown";
        }
        switch (status) {
            case 0:
                return "disabled";
            case 1:
                return "active";
            case 2:
                return "pending";
            default:
                return "unknown";
        }
    }
    
    /**
     * 创建用户会话
     * @param userId 用户ID
     * @param accessToken 访问令牌
     * @param refreshToken 刷新令牌
     */
    private void createUserSession(Long userId, String accessToken, String refreshToken) {
        UserSession session = new UserSession();
        session.setUserId(userId);
        session.setSessionToken(accessToken);
        session.setRefreshToken(refreshToken);
        
        // 设置过期时间
        LocalDateTime now = LocalDateTime.now();
        session.setExpiresAt(now.plusDays(1)); // 访问令牌24小时过期
        session.setRefreshExpiresAt(now.plusDays(7)); // 刷新令牌7天过期
        
        session.setCreatedAt(now);
        session.setUpdatedAt(now);
        session.updateLastActive();
        
        userSessionMapper.insert(session);
    }
    
    /**
     * 更新用户信息
     */
    @Override
    @Transactional
    public AuthResponse.UserInfo updateUserInfo(Long userId, String username, String nickname, String email, String newPassword) {
        try {
            User user = userMapper.selectById(userId);
            if (user == null) {
                throw new RuntimeException("用户不存在");
            }
            
            // 检查用户名是否已被其他用户使用
            if (!user.getUsername().equals(username) && !isUsernameAvailable(username)) {
                throw new RuntimeException("用户名已被使用");
            }
            
            // 检查邮箱是否已被其他用户使用
            if (!user.getEmail().equals(email) && !isEmailAvailable(email)) {
                throw new RuntimeException("邮箱已被使用");
            }
            
            // 更新用户信息
            user.setUsername(username);
            user.setNickname(nickname);
            user.setEmail(email);
            user.setUpdatedAt(LocalDateTime.now());
            
            // 如果提供了新密码，则更新密码
            if (newPassword != null && !newPassword.trim().isEmpty()) {
                user.setPassword(passwordEncoder.encode(newPassword));
                log.info("用户 {} 的密码已更新", username);
            }
            
            userMapper.updateById(user);
            
            // 构建并返回更新后的用户信息
            return AuthResponse.UserInfo.builder()
                    .id(user.getId())
                    .username(user.getUsername())
                    .nickname(user.getNickname())
                    .email(user.getEmail())
                    .avatar(user.getAvatar())
                    .role(user.getRole())
                    .status(convertStatusToString(user.getStatus()))
                    .emailVerified(user.getEmailVerified())
                    .createdAt(user.getCreatedAt())
                    .lastLoginAt(user.getLastLoginAt())
                    .build();
                    
        } catch (Exception e) {
            log.error("更新用户信息失败", e);
            throw new RuntimeException("更新用户信息失败: " + e.getMessage());
        }
    }
    
}